﻿using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace WhatCatch.Core2.UnitOfWork
{
    /// <summary>
    /// Repository基类
    /// </summary>
    /// <typeparam name="TEntity"></typeparam>
    public class RepositoryBase<TEntity> : IRepositoryBase<TEntity> where TEntity : class
    {
        protected DbContext _dbContext;

        public IQueryable<TEntity> Table => _dbContext.Set<TEntity>().AsQueryable();

        public IQueryable<TEntity> TableNoTracking => _dbContext.Set<TEntity>().AsNoTracking().AsQueryable();

        public RepositoryBase(DbContext dbContext)
        {
            _dbContext = dbContext;
        }

        public List<TEntity> GetAllList()
        {
            return _dbContext.Set<TEntity>().AsNoTracking().ToList();
        }
        public async Task<List<TEntity>> GetAllListAsync()
        {
            return await _dbContext.Set<TEntity>().AsNoTracking().ToListAsync();
        }

        public List<TEntity> GetList(Expression<Func<TEntity, bool>> predicate, bool isNoTracking = true)
        {
            var query = isNoTracking ? _dbContext.Set<TEntity>().AsNoTracking() : _dbContext.Set<TEntity>();
            return query.Where(predicate).ToList();
        }
        public async Task<List<TEntity>> GetListAsync(Expression<Func<TEntity, bool>> predicate, bool isNoTracking = true)
        {
            var query = isNoTracking ? _dbContext.Set<TEntity>().AsNoTracking() : _dbContext.Set<TEntity>();
            return await query.Where(predicate).ToListAsync();
        }
        public PageData<TEntity> GetPageList(Expression<Func<TEntity, bool>> predicate, int pageIndex, int pageSize, bool isNoTracking = true)
        {
            PageData<TEntity> pageData = new PageData<TEntity>();
            var query = isNoTracking ? _dbContext.Set<TEntity>().AsNoTracking() : _dbContext.Set<TEntity>();
            pageData.Items = query.Where(predicate).Skip(pageIndex * pageSize).Take(pageSize).ToList();
            pageData.PageIndex = pageIndex;
            pageData.PageSize = pageSize;
            pageData.ItemsCount = query.Count();

            return pageData;
        }
        public async Task<PageData<TEntity>> GetPageListAsync(Expression<Func<TEntity, bool>> predicate, int pageIndex, int pageSize, bool isNoTracking = true)
        {
            PageData<TEntity> pageData = new PageData<TEntity>();
            var query = isNoTracking ? _dbContext.Set<TEntity>().AsNoTracking() : _dbContext.Set<TEntity>();
            query = query.Where(predicate);
            return await PagingAsync(query, pageIndex, pageSize);
        }
        public async Task<PageData<T>> PagingAsync<T>(IQueryable<T> query, int pageIndex, int pageSize)
        {
            PageData<T> pageData = new PageData<T>();
            pageData.Items = await query.Skip(pageIndex * pageSize).Take(pageSize).ToListAsync();
            pageData.PageIndex = pageIndex;
            pageData.PageSize = pageSize;
            pageData.ItemsCount = await query.CountAsync();

            return pageData;
        }

        public TEntity GetModel(object id, bool isNoTracking = false)
        {
            //找到主键字段，特性[key]
            //特性值判断等于id

            //var query = isNoTracking ? _dbContext.Set<TEntity>() : _dbContext.Set<TEntity>().AsNoTracking();
            //var model = query.SingleOrDefault(c => c.Id == id);
            //return model;

            return null;
        }
        public async Task<TEntity> GetModelAsync(object id, bool isNoTracking = false)
        {
            //找到主键字段，特性[key]
            //特性值判断等于id

            //var query = isNoTracking ? _dbContext.Set<TEntity>() : _dbContext.Set<TEntity>().AsNoTracking();
            //var model = await query.SingleOrDefaultAsync(c => c.Id == id);
            //return model;

            return null;
        }

        public TEntity GetFirstModel()
        {
            var model = _dbContext.Set<TEntity>().AsNoTracking().FirstOrDefault();
            return model;
        }
        public async Task<TEntity> GetFirstModelAsync()
        {
            var model = await _dbContext.Set<TEntity>().AsNoTracking().FirstOrDefaultAsync();
            return model;
        }

        public int GetAllCount()
        {
            var model = _dbContext.Set<TEntity>().AsNoTracking().Count();
            return model;
        }
        public async Task<int> GetAllCountAsync()
        {
            var model = await _dbContext.Set<TEntity>().AsNoTracking().CountAsync();
            return model;
        }
        public int GetCount(Expression<Func<TEntity, bool>> predicate)
        {
            return _dbContext.Set<TEntity>().AsNoTracking().Where(predicate).Count();
        }
        public async Task<int> GetCountAsync(Expression<Func<TEntity, bool>> predicate)
        {
            return await _dbContext.Set<TEntity>().AsNoTracking().Where(predicate).CountAsync();
        }

        public bool Insert(TEntity entity)
        {
            _dbContext.Set<TEntity>().Add(entity);
            _dbContext.SaveChanges();
            return true;
        }
        public async Task<bool> InsertAsync(TEntity entity)
        {
            await _dbContext.Set<TEntity>().AddAsync(entity);
            await _dbContext.SaveChangesAsync();
            return true;
        }

        public bool Update(TEntity entity)
        {
            _dbContext.Entry<TEntity>(entity).State = EntityState.Modified;
            _dbContext.SaveChanges();
            return true;
        }
        public async Task<bool> UpdateAsync(TEntity entity)
        {
            _dbContext.Entry<TEntity>(entity).State = EntityState.Modified;
            await _dbContext.SaveChangesAsync();
            return true;
        }

        public bool Delete(object id)
        {
            var mode = GetModel(id);
            _dbContext.Set<TEntity>().Remove(mode);
            _dbContext.SaveChanges();
            return true;
        }
        //public async Task<bool> DeleteAsync(long id)
        //{
        //    var mode = await GetModelAsync(id);
        //    _dbContext.Set<TEntity>().Remove(mode);
        //    await _dbContext.SaveChangesAsync();
        //    return true;
        //}

        //public bool SoftDelete(long id)
        //{
        //    var mode = GetModel(id);
        //    mode.IsDelete = true;
        //    _dataContext.SaveChanges();
        //    return true;
        //}
        //public async Task<bool> SoftDeleteAsync(long id)
        //{
        //    var mode = await GetModelAsync(id);
        //    mode.IsDelete = true;
        //    await _dataContext.SaveChangesAsync();
        //    return true;
        //}

        ///// <summary>
        ///// 分页代码
        ///// </summary>
        ///// <typeparam name="T"></typeparam>
        ///// <param name="query"></param>
        ///// <param name="page"></param>
        ///// <returns></returns>
        //protected async Task<List<T>> Paging<T>(IQueryable<T> query, DataPage page)
        //{
        //    page.RecordCount = query.Count();
        //    page.PageSize = page.PageSize <= 0 ? 20 : page.PageSize;
        //    int totalCount = (int)Math.Ceiling(page.RecordCount / (double)page.PageSize);
        //    page.PageNo = page.PageNo > totalCount ? totalCount : page.PageNo;
        //    page.PageNo = page.PageNo <= 0 ? 1 : page.PageNo;
        //    return await query.Skip((page.PageNo - 1) * page.PageSize).Take(page.PageSize).ToListAsync() as List<T>;
        //}

        //IPagedList
        //protected async Task<IPagedList<T>> Paging<T>(IQueryable<T> query, DataPage page)
        //{

        //    page.RecordCount = query.Count();
        //    page.PageSize = page.PageSize <= 0 ? 20 : page.PageSize;
        //    int totalCount = (int)Math.Ceiling(page.RecordCount / (double)page.PageSize);
        //    page.PageNo = page.PageNo > totalCount ? totalCount : page.PageNo;
        //    page.PageNo = page.PageNo <= 0 ? 1 : page.PageNo;
        //    return await query.Skip((page.PageNo - 1) * page.PageSize).Take(page.PageSize).ToListAsync() as List<T>;
        //}

    }
}
